<?php
/*
* Copyright (c) 2010 by Cediti
*
* You may distribute under the terms of either the GNU Lesser General
* Public License or the new BSD License, as specified in the README file.
*/
// created :	31 March 2010
// version :	31 March 2010

class Cmis_Http_Response
{
	const RAW_HEADER = 0;
	const RAW_BODY = 1;

	// hard coded value from oasis CMIS specificcation
	protected $_responseMimeType = array(
        'cmis'  => array(
            Cmis_Services_Interface::FEED_TYPE_QUERY,//'application/cmisquery+xml', //CMIS Query document
            Cmis_Services_Interface::FEED_TYPE_ALLOWABLE_ACTIONS,//'application/cmisallowableactions+xml',//CMIS AllowableActions document
            Cmis_Services_Interface::FEED_TYPE_ATOM,//'application/cmisatom+xml', //* an Atom Document (Entry or Feed) with any CMIS Markup
            Cmis_Services_Interface::FEED_TYPE_HIERARCHY//'application/cmistree+xml',//* an Atom Feed Document with CMIS Hierarchy extensions (
	),
        'atom'  => array(
            Cmis_Services_Interface::FEED_TYPE_ATOM_PUB_SERVICE,//'application/atomsvc+xml',//AtomPub Service (
            Cmis_Services_Interface::FEED_TYPE_ATOM_APPLICATION,//'application/atom+xml',
            Cmis_Services_Interface::FEED_TYPE_ATOM_ENTRY,//'application/atom+xml;type=entry',//Atom Entry (
            Cmis_Services_Interface::FEED_TYPE_ATOM_FEED,//'application/atom+xml;type=feed',//Atom Feed (
	),
	);

	protected $_headers;

	protected $_body;

    protected $_version;

    protected $_code;

    protected $_status;

	protected $_raw;

	protected $_infos;

	public function __construct($response, array $adapter_info)
	{
		$this->_setRawResponse($response, $adapter_info['header_size']);
		$this->_infos = $adapter_info;
	}

	/**
	 * Get a raw data related to $key
	 * @param const $key
	 * @return string
	 */
	public function getRaw($key)
	{
		return $this->_raw[ $key ];
	}

	public function getMimeType()
	{
		return $this->getHeader('Content-Type');
	}

	public function getBody()
	{
		return $this->getRaw(self::RAW_BODY);
	}

	/**
     * Return the info corresponding to the key or the whole info if the key is null
     * Info coming from the Cmis_Adaper request
     * @param string $key
     * @return array|string
     */
    public function getInfo($key = null)
    {
        return ((is_null($key)) ? $this->_infos : $this->_infos[ $key ]);
    }

	/**
     * Return the header info corresponding to the key or the whole info if the key is null
     * @param string $key
     * @return array|string
	 */
	public function getHeader($key)
	{
		return ((is_null($key)) ? $this->_headers : $this->_headers[ $key ]);
	}

	public function getHTTPVersion()
	{
		return $this->_version;
	}

	public function getHTTPStatus()
	{
		return $this->_status;
	}

	public function getHTTPCode()
	{
		return $this->_code;
	}

   /**
     * Check if the response mime header is correct (compared to the type given)
     * @param string $type atom, cmis, ... if empty check in all kind of mime type
     * @return bool
     */
    public function checkResponseHeader($type = '')
    {
        if (!empty($type) && isset($this->_responseMimeType[ $type ]) )
        {
            return (in_array($this->getMimeType(), $this->_responseMimeType[ $type ]));
        }
        else
        {
            foreach($this->_responseMimeType as $v)
            {
                if (in_array($this->getMimeType(), $v))
                {
                    return true;
                }
            }
        }
        return false;
    }

    /**
     * @param bool $iterator if true return a SimpleXmlIterator
     * @return SimpleXMLElement|SimpleXmlIterator
     */
	public function toXml($iterator = false)
	{
		if (Debug::is_active())
		{
            Debug::var_debug($this);
            Debug::var_print($this->getHTTPCode(), $this->getHTTPStatus());
            Debug::var_xml($this->getRaw(self::RAW_BODY));
		}

		$iterator = ($iterator)?'SimpleXMLIterator':'SimpleXMLElement';

		//xmlns -> ns hack for php bug!
		//LIBXML_COMPACT @see http://be.php.net/manual/fr/libxml.constants.php
		return new $iterator(str_replace('xmlns=', 'ns=', $this->getRaw(self::RAW_BODY)), LIBXML_COMPACT & LIBXML_NSCLEAN);
	}

	public function __toString()
	{
		return implode("\n", $this->_raw);
	}

	protected function _setRawResponse($response, $header_size)
	{
		$this->_raw[ self::RAW_HEADER ] = str_replace("\r", '', substr($response, 0, $header_size));

		//extract header response
		if (preg_match_all('#([[:alpha:]-]+): ([[:print:]]*)#i', $this->_raw[ self::RAW_HEADER ], $matches, PREG_PATTERN_ORDER))
		{
			$this->_headers = array_combine($matches[1], $matches[2]);
		}
		else
		{
			$this->_headers = array();
		}

		$this->_extractHTTPInfo();

		$this->_raw[ self::RAW_BODY ] = substr($response, $header_size);
	}

	protected function _extractHTTPInfo($offset = 0)
	{
        if (preg_match('/HTTP\/(.+?) ([0-9]+) (.*)/i', $this->_raw[ self::RAW_HEADER ], $matches, null, $offset))
        {
        	//Debug::var_debug($matches, $offset, $this->_headers);
            $this->_version = $matches[1];
            $this->_code = intval($matches[2]);
            $this->_status = $matches[3];

            if ($this->_code == 100 && $this->_status = 'continue')
            {
            	return $this->_extractHTTPInfo(strpos($this->_raw[ self::RAW_HEADER ], $matches[0]) + 16);
            }
        }
        else
        {
            $this->_version = '1.0';
            $this->_code = 200;
            $this->_status = 'OK';
        }
	}
}

# EOF
